﻿using System;
using System.Collections;
using System.IO;
using System.Text;

namespace RaGE_JD
{
    internal class Condition : Object
    {
        public int OperID;
        public int ArgBytes;
        public byte[] Value;
        public int ConditionType;
        public Condition ConditionLeft;
        public int SubNodeL;
        public Condition ConditionRight;
        public int SubNodeR;

        internal static Condition LoadCondition(BinaryReader br)
        {
            var condition = new Condition();
            condition.OperID = br.ReadInt32();
            condition.ArgBytes = br.ReadInt32();
            condition.Value = br.ReadBytes(condition.ArgBytes);
            condition.ConditionType = br.ReadInt32();

            if (condition.ConditionType == 1)
            {
                condition.ConditionLeft = LoadCondition(br);
                condition.SubNodeL = br.ReadInt32();
                condition.ConditionRight = LoadCondition(br);
                condition.SubNodeR = br.ReadInt32();
            }

            if (condition.ConditionType == 2)
            {
                condition.ConditionRight = LoadCondition(br);
                condition.SubNodeL = br.ReadInt32();
            }
            return condition;
        }
    }

    internal class Procedure : Object
    {
        public int Type;
        public object[] Parameter;
        public int Target;
        public object[] TargetParams = null;
    }

    internal class ActionSet : Object
    {
        public int Version;
        public int ID;
        public byte[] Flags;
        public byte[] ActionSetName;
        public Condition Condition;
        public int ProcedureCount;
        public Procedure[] Procedure;

        public string Name
        {
            get
            {
                var encoding = Encoding.GetEncoding("GBK");
                return encoding.GetString(ActionSetName);
            }
            set
            {
                var encoding = Encoding.GetEncoding("GBK");
                var array = new byte[128];
                var bytes = encoding.GetBytes(value);

                if (array.Length > bytes.Length)
                    Array.Copy(bytes, array, bytes.Length);
                else
                {
                    Array nameStr1 = bytes;
                    var nameStr2 = array;
                    Array.Copy(nameStr1, nameStr2, nameStr2.Length);
                }

                ActionSetName = array;
            }
        }
    }

    internal class ActionController : Object
    {
        public int Signature;
        public int ID;
        public int ActionSetsCount;
        public ActionSet[] ActionSet;
    }

    internal class AIPolicy : Object
    {
        public int Signature;
        public int ActionControllerCount;
        public ActionController[] ActionController;

        // bool IsNumber(string)
        internal static bool IsNumber(string s)
        {
            if (s.Length != 0)
            {
                for (var i = 0; i < s.Length; i++)
                {
                    if (char.IsNumber(s[i])) continue;

                    if (s[i] != '.') return false;

                    if (i == 0) return false;

                    var text = s.Substring(i + 1);

                    if (!text.Contains(".")) continue;

                    return false;
                }
                return true;
            }
            return false;
        }

        // string GetNumber(string)
        internal static string GetNumber(string s)
        {
            var num = -1;
            var flag = true;

            for (var i = 0; i < s.Length; i++)
            {
                if (char.IsNumber(s[i])) num = i;
                else
                {
                    if (s[i] != '.' || !flag) break;
                    num = i;
                    flag = false;
                }
            }
            return num >= 0 ? s.Substring(0, num + 1) : "";
        }

        // bool IsMatch(string)
        internal static bool IsMatch(string s)
        {
            var stack = new Stack();
            var flag = true;

            for (var i = 0; i < s.Length; i++)
            {
                var text = s.Substring(i, 1);

                if (text == "(") stack.Push(text);

                if (text != ")") continue;

                if (stack.Count == 0)
                {
                    flag = false;
                    break;
                }

                stack.Pop();
            }

            return stack.Count == 0 && flag;
        }

        // int GetOperArgBytes(int)
        internal static int GetOperArgBytes(int operID)
        {
            switch (operID)
            {
                case 0:
                case 1:
                case 3:
                case 9:
                case 10:
                case 11:
                case 19:
                case 20:
                case 21:
                case 23:
                    return 4;

                default:
                    return 0;
            }
        }

        // int GetOperPrime(int)
        internal static int GetOperPrime(int operID)
        {
            switch (operID)
            {
                case 5:
                    return 2;

                case 6:
                case 7:
                case 16:
                case 17:
                case 18:
                    return 1;

                default:
                    return 3;
            }
        }

        // int IDOper(string)
        internal static int IDOper(string s)
        {
            switch (s)
            {
                case "a":
                    return 0;
                case "b":
                    return 1;
                case "c":
                    return 2;
                case "d":
                    return 3;
                case "e":
                    return 4;
                case "!":
                    return 5;
                case "f":
                    return 6;
                case "g":
                    return 7;
                case "h":
                    return 8;
                case "i":
                    return 9;
                case "j":
                    return 10;
                case "k":
                    return 11;
                case "l":
                    return 12;
                case "m":
                    return 13;
                case "n":
                    return 14;
                case "o":
                    return 15;
                case ">":
                    return 16;
                case "<":
                    return 17;
                case "=":
                    return 18;
                case "p":
                    return 19;
                case "q":
                    return 20;
                case "r":
                    return 21;
                case "s":
                    return 22;
                case "t":
                    return 23;
                default:
                    return -1;
            }
        }

        // int GetSubNodeL(int)
        internal static int GetSubNodeL(int operID)
        {
            switch (operID)
            {
                case 5:
                    return 4;

                case 6:
                case 7:
                case 16:
                case 17:
                case 18:
                    return 2;

                default:
                    return 0;
            }
        }

        // int GetSubNodeR(int)
        internal static int GetSubNodeR(int operID)
        {
            switch (operID)
            {
                case 6:
                case 7:
                case 16:
                case 17:
                case 18:
                    return 4;

                default:
                    return 0;
            }
        }
    }
}
